﻿using System.ComponentModel.Composition;
using MazeBuilder.Entities.Tiles;

namespace RoomModuleCatalog
{
  public enum TileCode
  {
    None = 0,
    Wall = 1,
    Door = 2,
    Floor = 3,
    Void = 4,
    Spade = 5,
    Flame = 6,
    Skull,
    Pentagram,
    Fountain
  }

  public abstract class Tile
  {
    public int Row { get; set; }
    public int Col { get; set; }
    public int ID { get; set; }
    public new abstract string ToString();
    public abstract int Code { get; }

    public bool Visited { get; set; }

    public override int GetHashCode() {
      return Code;
    }
  }

  //internal class ModuleExpressionFactory
  //{
  //  private static ModuleExpression expression = null;
  //  private static RoomFactory.eModule _seed = RoomFactory.eModule.None;
  //  public static ModuleExpression GetExpression(RoomFactory.eModule seed) {
  //    if (expression == null || (expression != null && seed != _seed))
  //      LoadExpression(seed);

  //    return expression;
  //  }

  //  //expression = (k % 6 != 0 && k > 1 && k < 5 && l % 6 != 0 && (l > 2 && l < 6 || l >6 && l < 10));
  //  //expression = ((k < 1 || k > 5 ) && (l > 2 && l < 6 || l >6 && l < 10));
  //  //expression = (k % 2 != 0) && (l > 0 && l < 12); 
  //  //expression = (l % 2 != 0) && ((k > 0 && k < 6) || (l > 0 && l < 2 && k != 0)) || (l > 2 && l < 4 && k != 6) || (l > 4 && l < 6 && k != 0) || (l > 6 && l < 8 && k != 6) || (l > 8 && l < 10 && k != 0) || (l > 10 && l < 12 && k != 6);
  //  //expression = (k % 3 != 0 && l % 4 == 0) || (k == 0 && l < 3) || (k == 0 && l > 9 && l < 13) || (k == 6 && l < 3) || (k == 6 && l > 9 && l < 13);
  //  //expression = (k % 3 != 0 && l % 4 == 0) || (k == 0 && l < 3) || (k == 0 && l > 9 && l < 13) || (k == 6 && l < 3) || (k == 6 && l > 9 && l < 13) || (k == 1 && l == 5) || (k == 1 && l == 7) || (k == 5 && l == 5) || (k == 5 && l == 7);
  //  //expression = (k > 1 && k < 5 && l > 4 && l < 8) || (k == 3 && l > 1 && l < 11);
  //  //expression = (k % 3 != 0 && l % 3 == 0 && k > 0 && l > 0 && l != 12) || (k % 2 != 0 && l %2 == 0 && k > 0 && l > 0 && l != 12); 
  //  //expression = (l % 4 == 0 && k != 0 && k != 6 && k != 3);
  //  //expression = (l % 4 != 0 && k != 0 && k != 6 && k != 3);
  //  //expression = (l % 4 == 1 && k != 0 && k != 6 && k != 3) || (l % 6 == 3 && k != 0 && k != 6 && k != 3);
  //  //expression = (l % 10 == 1 && k != 0 && k != 6);
  //  //expression = (k % 2 == 1 && l != 0 && l != 12);

  //  /// <exception cref="ArgumentOutOfRangeException"><c>seed</c> is out of range.</exception>
  //  private static void LoadExpression(RoomFactory.eModule seed) {
  //    ModuleExpression result = null;
  //    switch (seed) {
  //      case RoomFactory.eModule.ExprA:
  //        result = new ExprA();
  //        break;
  //      case RoomFactory.eModule.ExprB:
  //        result = new ExprB();
  //        break;
  //      case RoomFactory.eModule.ExprC:
  //        result = new ExprC();
  //        break;
  //      case RoomFactory.eModule.ExprD:
  //        result = new ExprD();
  //        break;
  //      case RoomFactory.eModule.ExprE:
  //        result = new ExprE();
  //        break;
  //      case RoomFactory.eModule.ExprF:
  //        result = new ExprF();
  //        break;
  //      case RoomFactory.eModule.ExprG:
  //        result = new ExprG();
  //        break;
  //      case RoomFactory.eModule.ExprH:
  //        result = new ExprH();
  //        break;
  //      case RoomFactory.eModule.ExprI:
  //        result = new ExprI();
  //        break;
  //      case RoomFactory.eModule.ExprL:
  //        result = new ExprL();
  //        break;
  //      case RoomFactory.eModule.ExprM:
  //        result = new ExprM();
  //        break;
  //      case RoomFactory.eModule.ExprN:
  //        result = new ExprN();
  //        break;
  //      case RoomFactory.eModule.ExprO:
  //        result = new ExprO();
  //        break;
  //      default:
  //        throw new ArgumentOutOfRangeException("seed");
  //    }

  //    expression = result;
  //  }
  //}

  public abstract class ModuleExpression : IModuleExpression
  {
    public abstract bool getExpressionResult(int i, int j);
    public abstract Tile getTile(int i, int i1);
  }

  public interface IModuleExpression
  {
    bool getExpressionResult(int i, int j);
    Tile getTile(int i, int i1);
  }

  abstract class VoidExpression : ModuleExpression
  {
    public override Tile getTile(int i, int i1) {
      Tile result = new VoidTile(-1, -1);

      return result;
    }
  }

  abstract class StoneExpression : ModuleExpression
  {
    public override Tile getTile(int i, int i1) {
      Tile result = new WallTile(-1, -1);

      return result;
    }
  }

#if DEBUG
  [Export(typeof(IModuleExpression))]
  internal class ExprT_S : StoneExpression
  {
    public override bool getExpressionResult(int k, int l) {
      //return ((k % 2 == 0) && (l % 2 != 0) && (l % 3 != 0) && (k != 0 && k != 6));
      return ((((k % 2 == 0) && (k % 4 == 0) && (l % 4 != 0)) || ((k % 2 == 0) && (k % 4 != 0) && (l % 4 == 0))) && (l != 0 && l != 12) && (k != 0 && k != 6));
    }
  }

#endif

#if !DEBUG

  #region stones

  [Export(typeof(IModuleExpression))]
  internal class ExprV_S : StoneExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return ((((k % 2 == 0) && (k % 4 == 0) && (l % 4 != 0)) || ((k % 2 == 0) && (k % 4 != 0) && (l % 4 == 0))) && (l != 0 && l != 12) && (k != 0 && k != 6));
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprV : VoidExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return ((((k % 2 == 0) && (k % 4 == 0) && (l % 4 != 0)) || ((k % 2 == 0) && (k % 4 != 0) && (l % 4 == 0))) && (l != 0 && l != 12) && (k != 0 && k != 6));
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprU : VoidExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return ((k % 2 == 0) && (l % 2 != 0) && (l % 3 != 0) && (k != 0 && k != 6));
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprU_S : StoneExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return ((k % 2 == 0) && (l % 2 != 0) && (l % 3 != 0) && (k != 0 && k != 6));
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprT_S : StoneExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return ((k == 3 && l != 0 && l != 6 && l != 12) || (l == 6 && k != 0 && k != 6));
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprA_S : StoneExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return (k % 6 != 0 && k > 1 && k < 5 && l % 6 != 0 && (l > 2 && l < 6 || l > 6 && l < 10));
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprB_S : StoneExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return ((k < 1 || k > 5) && (l > 2 && l < 6 || l > 6 && l < 10));
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprC_S : StoneExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return (k % 2 != 0) && (l > 0 && l < 12);
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprD_S : StoneExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return (l % 2 != 0) && ((k > 0 && k < 6) || (l > 0 && l < 2 && k != 0)) || (l > 2 && l < 4 && k != 6) ||
             (l > 4 && l < 6 && k != 0) || (l > 6 && l < 8 && k != 6) || (l > 8 && l < 10 && k != 0) ||
             (l > 10 && l < 12 && k != 6);
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprE_S : StoneExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return (k % 3 != 0 && l % 4 == 0) || (k == 0 && l < 3) || (k == 0 && l > 9 && l < 13) || (k == 6 && l < 3) ||
             (k == 6 && l > 9 && l < 13);
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprF_S : StoneExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return (k % 3 != 0 && l % 4 == 0) || (k == 0 && l < 3) || (k == 0 && l > 9 && l < 13) || (k == 6 && l < 3) ||
             (k == 6 && l > 9 && l < 13) || (k == 1 && l == 5) || (k == 1 && l == 7) || (k == 5 && l == 5) ||
             (k == 5 && l == 7);
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprG_S : StoneExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return (k > 1 && k < 5 && l > 4 && l < 8) || (k == 3 && l > 1 && l < 11);
    }
  }

  #endregion

  [Export(typeof(IModuleExpression))]
  internal class ExprH_S : StoneExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return (k % 3 != 0 && l % 3 == 0 && k > 0 && l > 0 && l != 12) || (k % 2 != 0 && l % 2 == 0 && k > 0 && l > 0 && l != 12);
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprI_S : StoneExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return (l % 4 == 0 && k != 0 && k != 6 && k != 3);
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprL_S : StoneExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return (l % 4 != 0 && k != 0 && k != 6 && k != 3);
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprM_S : StoneExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return (l % 4 == 1 && k != 0 && k != 6 && k != 3) || (l % 6 == 3 && k != 0 && k != 6 && k != 3);
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprN_S : StoneExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return (l % 10 == 1 && k != 0 && k != 6);
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprO_S : StoneExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return (k % 2 == 1 && l != 0 && l != 12);
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprP_S : StoneExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return ((k % 3 != 0) && (k % 2 == 1) && (k > 0) && (l > 0) && (l < 12) && (l % 2 == 0));
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprQ_S : StoneExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return ((k % 6 != 0) && (l != 0) && (l != 12));
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprR_S : StoneExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return ((k % 5 != 1) && (l != 0) && (l != 12) && (l != 6));
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprS_S : StoneExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return ((k % 5 == 2) && (l != 0) && (l != 12) && (l != 6) || ((l % 3 == 0) && (l != 0) && (l != 12) && (l != 6) && (k != 0) && (k != 6)));
    }
  }


  #region voids

  [Export(typeof(IModuleExpression))]
  internal class ExprA : VoidExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return (k % 6 != 0 && k > 1 && k < 5 && l % 6 != 0 && (l > 2 && l < 6 || l > 6 && l < 10));
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprB : VoidExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return ((k < 1 || k > 5) && (l > 2 && l < 6 || l > 6 && l < 10));
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprC : VoidExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return (k % 2 != 0) && (l > 0 && l < 12);
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprD : VoidExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return (l % 2 != 0) && ((k > 0 && k < 6) || (l > 0 && l < 2 && k != 0)) || (l > 2 && l < 4 && k != 6) ||
             (l > 4 && l < 6 && k != 0) || (l > 6 && l < 8 && k != 6) || (l > 8 && l < 10 && k != 0) ||
             (l > 10 && l < 12 && k != 6);
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprE : VoidExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return (k % 3 != 0 && l % 4 == 0) || (k == 0 && l < 3) || (k == 0 && l > 9 && l < 13) || (k == 6 && l < 3) ||
             (k == 6 && l > 9 && l < 13);
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprF : VoidExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return (k % 3 != 0 && l % 4 == 0) || (k == 0 && l < 3) || (k == 0 && l > 9 && l < 13) || (k == 6 && l < 3) ||
             (k == 6 && l > 9 && l < 13) || (k == 1 && l == 5) || (k == 1 && l == 7) || (k == 5 && l == 5) ||
             (k == 5 && l == 7);
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprG : VoidExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return (k > 1 && k < 5 && l > 4 && l < 8) || (k == 3 && l > 1 && l < 11);
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprH : VoidExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return (k % 3 != 0 && l % 3 == 0 && k > 0 && l > 0 && l != 12) || (k % 2 != 0 && l % 2 == 0 && k > 0 && l > 0 && l != 12);
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprI : VoidExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return (l % 4 == 0 && k != 0 && k != 6 && k != 3);
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprL : VoidExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return (l % 4 != 0 && k != 0 && k != 6 && k != 3);
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprM : VoidExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return (l % 4 == 1 && k != 0 && k != 6 && k != 3) || (l % 6 == 3 && k != 0 && k != 6 && k != 3);
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprN : VoidExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return (l % 10 == 1 && k != 0 && k != 6);
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprO : VoidExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return (k % 2 == 1 && l != 0 && l != 12);
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprP : VoidExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return ((k % 3 != 0) && (k % 2 == 1) && (k > 0) && (l > 0) && (l < 12) && (l % 2 == 0));
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprQ : VoidExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return ((k % 6 != 0) && (l != 0) && (l != 12));
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprR : VoidExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return ((k % 5 != 1) && (l != 0) && (l != 12) && (l != 6));
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprS : VoidExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return ((k % 5 == 2) && (l != 0) && (l != 12) && (l != 6) || ((l % 3 == 0) && (l != 0) && (l != 12) && (l != 6) && (k != 0) && (k != 6)));
    }
  }

  [Export(typeof(IModuleExpression))]
  internal class ExprT : VoidExpression
  {
    public override bool getExpressionResult(int k, int l) {
      return ((k == 3 && l != 0 && l != 6 && l != 12) || (l == 6 && k != 0 && k != 6));
    }
  }

  #endregion


#endif

}
